home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************/
- /* */
- /* COMPC.C Compression de fichiers source C. */
- /* V1.00 FREEWARE Christian BRUNON 20-08-1993 */
- /* */
- /* +-----------------------------------------+ */
- /* | Logiciel placé dans le domaine FREEWARE | */
- /* +-----------------------------------------+ */
- /* L'utilisation et la diffusion de ce programme, des fichiers sources */
- /* et de la documentation sont entièrement libres. */
- /* */
- /* Christian BRUNON */
- /* 30 Rue Georges Brassens */
- /* 43140 LA SEAUVE SUR SEMENE */
- /* FRANCE */
- /* */
- /* Fichier source Lattice C AmigaDOS Version 5.04 */
- /* */
- /*************************************************************************/
-
- /* Fichier INCLUDE */
- #include "CPRG:CompC.H"
-
- /* MACROS */
- #define IsValide(C) (((C)=='_') || ((UpChar(C)>'/') && (UpChar(C)<'[')))
- #define IsInitiale(C) (((C)=='#') || (IsValide(C)))
-
- /* Autre constante d'erreur */
- #define CompError 8
-
- /* Autre constante */
- #define MaxLongLigne 255
-
- UBYTE Ligne[MaxLongLigne], /* Ligne de texte à compresser */
- LigneComp[MaxLongLigne], /* Ligne de texte compressée */
- NuCar; /* Numéro du caractère inséré dans la chaîne Ligne */
-
- typedef struct {
- UWORD CodeMot;
- UBYTE Mot[MaxLongMot];
- } StructMot;
-
- static StructMot ListeMots[MaxMots];
-
- static UWORD PosMot; /* Position du nouveau mot à insérer */
-
- static ULONG LongFicOut;
-
- const UBYTE *ListeErreurs[] =
- {
- "\n",
- "Utilisation : CompC [-DEST] Fichier1 [-DEST] [Fichier2] [...]\n",
- "\aFichier inexistant\n",
- "\aErreur en création\n",
- "\aErreur en écriture\n",
- "\aErreur en lecture\n",
- "\aPas assez de mémoire\n",
- "\a***BREAK\n",
- "\aCompression inefficace\n"
- };
-
- extern int (*_ONBREAK)();
-
- /**************************************************************************/
-
- int CXBRK()
- {
- CodeErreur=BreakError;
-
- return(0);
- }
-
- /**************************************************************************/
-
- #ifdef OOOOOOOOO
- /* INUTILISE car provoquant des compressions moins importantes */
- int IsValide(UBYTE C)
- {
- return((C=='_') | (C=='ç') | (C=='é') | (C=='è') | (C=='ê') |
- (C=='à') | (C=='ù') | (C=='ä') | (C=='ë') | (C=='ï') |
- (C=='ö') | (C=='ü') | (C=='â') | (C=='î') | (C=='ô') |
- (C=='û') | (C=='\'') | ((UpChar(C)>'/') && (UpChar(C)<'[')));
- }
- #endif
-
- /**************************************************************************/
-
- UBYTE InsererMot()
- {
- register UWORD i;
-
- if(NbMots==0)
- {
- strcpy(ListeMots[0].Mot,Mot);
- ListeMots[0].CodeMot=0;
- NbMots=1;
- }
- else if(NbMots<MaxMots)
- {
- /* Décaler la partie supérieure du tableau pour libérer une place */
- if(PosMot<NbMots) for(i=NbMots;i>PosMot;i--) ListeMots[i]=ListeMots[i-1];
-
- /* Insertion du mot */
- strcpy(ListeMots[PosMot].Mot,Mot);
- ListeMots[PosMot].CodeMot=NbMots;
- NbMots++;
- }
- /* Le dictionnaire est plein */
- else return(CodeErreur=MemoryError);
-
- return(0);
- }
-
- /**************************************************************************/
- /* Recherche un mot dans la liste de ceux déjà enregistrés. */
- /* Si le mot ne s'y trouve pas il est inséré dans la liste par appel à la */
- /* fonction InsererMot(). */
- /* Elle insère le nouveau mot à la position PosMot si la liste n'est pas */
- /* vide. */
- /* Si elle est vide, le mot est inséré à la première place */
- /* Cette fonction renvoie 1 si le mot est dans la liste. */
- /* Sinon, elle l'insère et renvoie 0. */
- /**************************************************************************/
-
- UBYTE TrouverMot()
- {
- /* Le mot est peut-être dans la liste */
- if(NbMots)
- {
- /* Le mot est-il inférieur au dernier mot de la liste ? */
- if(strcmp(ListeMots[NbMots-1].Mot,Mot)>=0)
- {
- PosMot=0;
-
- /* Recherche sur le premier caractère de la chaîne */
- while(ListeMots[PosMot].Mot[0]<Mot[0]) PosMot++;
- /* Recherche sur les autres caractères */
- while(strcmp(ListeMots[PosMot].Mot,Mot)<0) PosMot++;
-
- if(strcmp(ListeMots[PosMot].Mot,Mot)==0)
- {
- /* Le mot est déjà dans la liste */
- CodeMot=ListeMots[PosMot].CodeMot;
- return(1);
- }
- else CodeErreur=InsererMot(); /* Le mot n'est pas dans la liste */
- }
- else{
- /* Le mot est plus grand que le dernier mot de la liste */
- /* On l'insère en dernière position. */
- PosMot=NbMots;
- CodeErreur=InsererMot();
- } /* if(strcmp(ListeMots[NbMots-1].Mot,Mot)>=0) */
-
- }
- else CodeErreur=InsererMot(); /* Mot non trouvé (NbMots=0) */
-
- return(0);
- }
-
- /**************************************************************************/
-
- UBYTE CompresserLigne()
- {
- Ligne[NuCar]='\0';
-
- /* Effacement des espaces se trouvant en fin de chaîne */
- while(NuCar && (Ligne[NuCar-1]==' ' || Ligne[NuCar-1]=='\t')) Ligne[--NuCar]='\0';
-
- if(NuCar==0){
- if(fputc(LigneVide,FOut)==EOF) return(WriteError);
- }
- else{
- NuCar=0;
-
- /* Calcul du nombre d'espaces en début de ligne dans NuCar */
- while(Ligne[NuCar]==' ' || Ligne[NuCar]=='\t') NuCar++;
-
- /* Suppression du nombre d'espaces en début de ligne */
- if(NuCar) strcpy(Ligne,Ligne+NuCar);
-
- /* Ecriture du nombre d'espaces en début de ligne */
- if(fputc(NuCar,FOut)==EOF) return(WriteError);
-
- for(NuCar=0 ; NuCar<strlen(Ligne) && CodeErreur==0;)
- {
- /* Un mot détecté */
- if(IsInitiale(Ligne[NuCar]))
- {
- /* Copie de l'initiale du mot dans le premier car de mot */
- Mot[0]=Ligne[NuCar++];
- LongMot=1;
-
- /* Copie du reste du mot */
- while(IsValide(Ligne[NuCar])) Mot[LongMot++]=Ligne[NuCar++];
- /* Ajout de la parenthèse ouverte ou du crochet ouvert si il suit */
- if(Ligne[NuCar]=='(' || Ligne[NuCar]=='[') Mot[LongMot++]=Ligne[NuCar++];
-
- Mot[LongMot]=0;
-
- /* Ecriture du mot ou de son code */
- if(LongMot<3)
- {
- if(fputs(Mot,FOut)) return(WriteError);
- }
- else{
- /* Mot répertorié ? */
- if(TrouverMot())
- {
- /* Le mot existe, on écrit son code */
- if(fprintf(FOut,"%c%c%c",MotExistant,CodeMot&255,CodeMot>>8)==-1) return(WriteError);
- }
- /* Nouveau mot */
- else{
- /* Le mot est nouveau, on l'écrit encadré par */
- /* les marques de nouveau mot */
- if(fprintf(FOut,"%c%s%c",NouveauMot,Mot,NouveauMot)==-1) return(WriteError);
- }
- } /* if(LongMot<3) */
-
- } /* if(IsInitiale(Ligne[NuCar])) */
-
- /* Début de commentaire */
- else if(Ligne[NuCar]=='/' && Ligne[NuCar+1]=='*')
- {
- /* Début de commentaire + espace */
- if(Ligne[NuCar+2]==' ')
- {
- NuCar+=3;
- if(fputc(Commentaire2On,FOut)==EOF) return(WriteError);
- }
- else{
- NuCar+=2;
- if(fputc(Commentaire1On,FOut)==EOF) return(WriteError);
- }
- }
-
- /* Fin de commentaire */
- else if(Ligne[NuCar]=='*' && Ligne[NuCar+1]=='/')
- {
- NuCar+=2;
- if(fputc(Commentaire1Off,FOut)==EOF) return(WriteError);
- }
-
- /* Espace + fin de commentaire */
- else if(Ligne[NuCar]==' ' && Ligne[NuCar+1]=='*' && Ligne[NuCar+2]=='/')
- {
- NuCar+=3;
- if(fputc(Commentaire2Off,FOut)==EOF) return(WriteError);
- }
-
- /* Autre caractère */
- else while(!IsInitiale(Ligne[NuCar]) && Ligne[NuCar])
- if(fputc(Ligne[NuCar++],FOut)==EOF) return(WriteError);
-
- } /* for(NuCar=0;NuCar<strlen(Ligne);) */
-
- if(fputc('\n',FOut)==EOF) return(WriteError);
-
- /* Affichage du nombre d'octets lus */
- if(!ComptLignes++) printf("%7u\b\b\b\b\b\b\b",ftell(FIn));
-
- ComptLignes%=10;
- NuCar=0;
- }
-
- return(CodeErreur);
- }
-
- /**************************************************************************/
-
- UBYTE CompresserFichier()
- {
- /* VARIABLE LOCALE */
- register int Car; /* Caractère lu dans le fichier */
-
- /* Le fichier est-il vide ? */
- /* if(((Car=fgetc(FIn))==EOF)&&(feof(FIn))) */
- /* { */
- /* printf("Fichier vide.\n"); */
- /* return(1); */
- /* } */
- /* */
- /* Fichier non vide : on replace le caractère lu dans le buffer */
- /* ungetc(Car,FIn); */
-
- printf("Création du fichier %s -> %7u -> ",NomFicOut,LongFicIn);
-
- LongFicOut=0L;
- if((FOut=fopen(NomFicOut,"wb"))==NULL) return(CreateError);
-
- Car=fgetc(FIn);
-
- ComptLignes=NuCar=NbMots=0;
-
- while(FIn->_flag==_IOREAD && CodeErreur==0)
- {
- if(Car=='\n') CodeErreur=CompresserLigne();
- else Ligne[NuCar++]=Car;
-
- Car=fgetc(FIn);
- }
-
- /* Erreur en lecture ou fin normal de fichier ? */
- if(FIn->_flag != (_IOREAD|_IOEOF)) return(ReadError);
-
- if(CodeErreur==0 && NuCar) CodeErreur=CompresserLigne();
-
- return(CodeErreur);
- }
-
- /**************************************************************************/
-
- int main(int argc,char *argv[])
- {
- /* Déclarations et fonctions de Exec.Library */
- extern struct ExecBase *SysBase;
- extern void FreeMem(void *,long);
- extern void *AllocMem(long,long);
- #pragma syscall AllocMem c6 1002
- #pragma syscall FreeMem d2 902
-
- register struct FileInfoBlock *PtrFIB;
-
- /* Déclarations de variables externes de la DOS.Library */
- extern struct DosLibrary *DOSBase;
- extern BPTR CreateDir(char *);
- extern long DeleteFile(char *);
- extern long SetProtection(char *, ULONG);
- extern LONG SetComment(char *, char *);
- extern LONG Examine(BPTR, struct FileInfoBlock *);
- extern BPTR Lock(char *, LONG);
- extern void UnLock(BPTR);
- #pragma libcall DOSBase CreateDir 78 101
- #pragma libcall DOSBase DeleteFile 48 101
- #pragma libcall DOSBase SetProtection ba 2102
- #pragma libcall DOSBase SetComment b4 2102
- #pragma libcall DOSBase Examine 66 2102
- #pragma libcall DOSBase Lock 54 2102
- #pragma libcall DOSBase UnLock 5a 101
-
- /* VARIABLES LOCALES */
- register UBYTE NuArg,
- FlagNewDir=0, /* Changer le répertoire de destination ? */
- CreerChemin=0, /* Créer le nouveau répertoire ? */
- NewChemin[80],
- FileName[108],
- Commentaire[80];
-
- register BPTR Clef; /* Paramètre utilisé pour Examine() et CreateDir() */
-
- register ULONG Protection;
-
- /*********************** DEBUT DU CODE DE main() **************************/
-
- _ONBREAK=CXBRK;
-
- printf("CompC V1.00 FREEWARE Christian BRUNON 20-08-1993\n");
-
- /* Pas de paramètre ou paramètre ? */
- if(argc==1 || (argc==2 && argv[1][0]=='?' && argv[1][1]=='\0'))
- {
- printf("%s",ListeErreurs[1]);
- return(1);
- }
-
- if((PtrFIB=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),0L))==NULL)
- {
- printf("%s",ListeErreurs[MemoryError]);
- return(MemoryError);
- }
-
- for(NuArg=1;NuArg<argc;NuArg++)
- if(argv[NuArg][0]=='-')
- /* Le paramètre lu est un nouveau chemin */
- {
- FlagNewDir=(UBYTE)1;
- strcpy(NewChemin,&argv[NuArg][1]);
-
- if(NewChemin[0]) CreerChemin=LastChar(NewChemin)!=':' && LastChar(NewChemin)!='/';
-
- if(CreerChemin && NewChemin[0])
- {
- if(Clef=CreateDir(NewChemin)) UnLock(Clef);
-
- strcat(NewChemin,"/");
- }
- }
- /* Le paramètre lu est un fichier à compresser */
- else{
- CodeErreur=0;
- strcpy(NomFicIn,argv[NuArg]);
-
- if(Clef=Lock(NomFicIn,ACCESS_READ))
- {
- /* Test existence et test type = fichier */
- if(Examine(Clef,PtrFIB) && PtrFIB->fib_DirEntryType<0)
- {
- strcpy(FileName,PtrFIB->fib_FileName);
- LongFicIn=PtrFIB->fib_Size;
- Protection=(ULONG)PtrFIB->fib_Protection;
- strcpy(Commentaire,PtrFIB->fib_Comment);
- }
- else CodeErreur=FileOpenReadError;
-
- UnLock(Clef);
- }
- else CodeErreur=FileOpenReadError;
-
- if(CodeErreur){
- printf("%s %s",NomFicIn,ListeErreurs[CodeErreur]);
- continue;
- }
-
- /* Détermination du nom du fichier compressé */
- if(FlagNewDir)
- {
- strcpy(NomFicOut,NewChemin);
- strcat(NomFicOut,FileName);
- }
- else strcpy(NomFicOut,NomFicIn);
-
- /* Rajout de l'extension ".K" */
- strcat(NomFicOut,".K");
-
- printf("Ouverture du fichier %s\r",NomFicIn);
-
- if(FIn=fopen(NomFicIn,"rb"))
- {
- CodeErreur=CompresserFichier();
-
- /* Affichage du taux de compression ou du texte de l'erreur */
- if(CodeErreur==0)
- {
- printf("%7u => ",LongFicOut=ftell(FOut));
-
- if(LongFicIn && LongFicOut<=LongFicIn)
- printf("%u %%\n",(((100*(LongFicIn-LongFicOut))/LongFicIn)*10+5)/10);
- else CodeErreur=CompError;
- }
- else printf("\n%s",ListeErreurs[CodeErreur]);
-
- if(FIn) fclose(FIn);
- if(FOut) fclose(FOut);
-
- if(CodeErreur) DeleteFile(NomFicOut);
- else /* Recopie des bits d'attributs de fichier et du commentaire */
- {
- SetProtection(NomFicOut,Protection);
- SetComment(NomFicOut,Commentaire);
- }
- }
- /* Fichier inexistant ou illisible */
- else printf("\n%s",ListeErreurs[CodeErreur=FileOpenReadError]);
- }
-
- if(PtrFIB) FreeMem(PtrFIB,sizeof(struct FileInfoBlock));
-
- /* Renvoie le code d'erreur du dernier fichier compressé */
- return(CodeErreur);
- }
-